/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package BayesNetwork;

import java.util.ArrayList;

/**
 *
 * @author Jedrek
 */
public class BayesNode {
    int parentCount = 0;
    int childrenCount = 0;

    ArrayList<BayesNode> parents;
    ArrayList<BayesNode> children;

    ProbabilityNode probabilityNode = null;
    String name;

    int memorySize = 100;

    public BayesNode(String name){
        parents = new ArrayList<BayesNode>();
        children = new ArrayList<BayesNode>();
        probabilityNode = new ProbabilityNode(this, 0.5f);
        this.name = name;
//        System.out.println("Node created: " + name);
    }

    public BayesNode(String name, float trueProbability){
        parents = new ArrayList<BayesNode>();
        children = new ArrayList<BayesNode>();
        probabilityNode = new ProbabilityNode(this, trueProbability);
        this.name = name;
//        System.out.println("Node created: " + name);
    }

    public void addParent(BayesNode node){
        probabilityNode = new ProbabilityNode(node, probabilityNode, probabilityNode.copy());

        parents.add(node);
        parentCount++;
    }
    
    public void addChild(BayesNode node){
       children.add(node);
       childrenCount++;

       node.addParent(this);
    }

    public float getTrueProbability(ArrayList<String> event){
        float trueProbability = 0;
        float falseProbability = 0;
        
        trueProbability = probabilityNode.getTrueProbability(event);
        falseProbability = 1-probabilityNode.getTrueProbability(event);

        for( int i = 0; i<event.size(); i++ ){
            String nodeName = event.get(i).substring(0, event.get(i).length()-2);
            if( nodeName == null )
                continue;
            if( !hasChild(nodeName) )
                continue;
            char val = event.get(i).charAt(event.get(i).length()-1);
            val = Character.toUpperCase(val);
            BayesNode node = getChild(nodeName);
            if( node == null )
                continue;

            if( val == 'T' ){
                trueProbability *= node.getTrueProbability(name+"=T");
                falseProbability *= node.getTrueProbability(name+"=F");
            } else if (val == 'F' ){
                trueProbability *= 1-node.getTrueProbability(name+"=T");
                falseProbability *= 1-node.getTrueProbability(name+"=F");
            }
        }

        trueProbability = trueProbability/(trueProbability+falseProbability);
        
        return trueProbability;
    }

    public float getTrueProbability(String event){
        ArrayList<String> arrayEvent = new ArrayList<String>();

        if(event.length()<=0)
            return getTrueProbability(arrayEvent);

        String[] array = event.split(",");
        for(int i = 0; i<array.length; i++){
            arrayEvent.add(array[i].trim());
        }
        return getTrueProbability(arrayEvent);
    }
    
    public void setTrueProbability(ArrayList<String> event, float value){
        probabilityNode.setTrueProbability(event, value);
    }

    public void setTrueProbability(String event, float value){
        ArrayList<String> arrayEvent = new ArrayList<String>();

        if(event.length()<=0)
            probabilityNode.setTrueProbability(arrayEvent, value);
        
        String[] array = event.split(",");
        for(int i = 0; i<array.length; i++){
            arrayEvent.add(array[i].trim());
        }
        probabilityNode.setTrueProbability(arrayEvent, value);
    }

    public String getName(){
        return name + "";   //this ' + "" ' is supposed to cause that a copy of a name is returned, not the object itself. I don't know if it works
    }

    @Override
    public String toString(){
        return name + "";
    }

    public boolean hasChild(String parentName){
        for(int i = 0; i<children.size(); i++)
            if(children.get(i).getName().compareTo(parentName) == 0)
                return true;

        return false;
    }
    
    public boolean teach(ArrayList<String> event){
        return probabilityNode.teachNode(event, 1f);
    }

    BayesNode getChild(String nodeName){
        for(int i = 0; i<children.size(); i++)
            if(children.get(i).getName().compareTo(nodeName) == 0)
                return children.get(i);

        return null;
    }
}
